#ifndef CEntidad_hpp
#define CEntidad_hpp

class CAplicacion;
class CUtiles;

#include "CAplicacion.hpp"
#include "CUtiles.hpp"

#include <Ogre.h>
#include <NxPhysics.h>

using namespace std;
using namespace Ogre;

//Unidad : KG/m3
//http://www.kalipedia.com/fisica-quimica/tema/estructura-materia/tabla-densidades-25-%B0c.html?x1=20070924klpcnafyq_22.Kes&x=20070924klpcnafyq_25.Kes
enum DENSIDAD
{
	//Solidos
	Aluminio = 2700,
	Corcho = 250,
	Cobre = 8960,
	Hielo = 920,
	Hierro = 7900,
	MaderaPocoDensa = 200,
	MaderaDensidadMedia = 500,
	MaderaMuyDensa = 800,
	Plomo = 11300 ,
	VidrioPocoDenso = 3000,
	VidrioMuyDenso = 3600,

	//Liquidos
	Acetona = 790 ,
	Aceite = 920 ,
	AguaDeMar = 1025 ,
	AguaDestilada = 1000 ,
	AlcoholEtilico = 790 ,
	Gasolina = 680 ,
	Leche = 1030 ,
	Mercurio = 13600,

	//Gas
	Aire = 1,
	Butano = 3
};

enum GRUPOS_DE_COLISION
{
	DEFECTO,
	CAMARA,
	TERRENO
};

class CEntidad
{
public:

	//En 0,0,0
	CEntidad();

	//Constructor forma cubo
	CEntidad(Vector3 posActor);

	//Destructor
	virtual ~CEntidad();

	void anadirFormaCubo
	(
		string nombreForma , 
		DENSIDAD densidad , 
		float ancho , 
		float alto , 
		float fondo,
		const NxVec3* initialVelocity,
		String texture
	);
	void anadirFormaEsfera(string nombreForma , DENSIDAD densidad , float radio);
	void anadirFormaMesh(string nombreForma , string rutaMesh , Quaternion orientacion , NxVec3 escalaRender , DENSIDAD densidad);
	void anadirFormaPlano(string nombreForma , DENSIDAD densidad , float ancho , float fondo);
	void anadirFormaSuelo(string nombreForma , DENSIDAD densidad , float ancho , float fondo);
	void anadirFormaCapsula(string nombreForma , DENSIDAD densidad , float radio , float altura);

	void quitarSombras();

	//void reportarContacto(NxContactPairFlag flags);

	virtual void refrescar(Real tiempoDesdeUltimoFrame = 0);

	//Modifican la entidad por simulacion
	void anadirFuerza(NxVec3 fuerza , NxForceMode tipoFuerza);
	void anadirTorsion(NxVec3 fuerza , NxForceMode tipoFuerza);

	//Movimeintos por fuerzas
	void setFuerzaAcelerar(float paso , NxForceMode tipoFuerza){anadirFuerza(NxVec3(0,0,-paso),tipoFuerza);}
	void setFuerzaFrenar(float paso , NxForceMode tipoFuerza){anadirFuerza(NxVec3(0,0,paso),tipoFuerza);}
	void setFuerzaSubir(float paso , NxForceMode tipoFuerza){anadirFuerza(NxVec3(0,paso,0),tipoFuerza);}
	void setFuerzaBajar(float paso , NxForceMode tipoFuerza){anadirFuerza(NxVec3(0,-paso,0),tipoFuerza);}
	void setFuerzaEstrafearDerecha(float paso , NxForceMode tipoFuerza){anadirFuerza(NxVec3(paso,0,0),tipoFuerza);}
	void setFuerzaEstrafearIzquierda(float paso , NxForceMode tipoFuerza){anadirFuerza(NxVec3(-paso,0,0),tipoFuerza);}

	//Giros por fuerzas
	void setTorsionGirarDerecha(float paso , NxForceMode tipoFuerza){anadirTorsion(NxVec3(0,0,-paso),tipoFuerza);}
	void setTorsionGirarIzquierda(float paso , NxForceMode tipoFuerza){anadirTorsion(NxVec3(0,0,paso),tipoFuerza);}
	void setTorsionMirarArriba(float paso , NxForceMode tipoFuerza){anadirTorsion(NxVec3(0,paso,0),tipoFuerza);}
	void setTorsionMirarAbajo(float paso , NxForceMode tipoFuerza){anadirTorsion(NxVec3(0,-paso,0),tipoFuerza);}
	void setTorsionInclinarMiradaDerecha(float paso , NxForceMode tipoFuerza){anadirTorsion(NxVec3(paso,0,0),tipoFuerza);}
	void setTorsionInclinarMiradaIzquierda(float paso , NxForceMode tipoFuerza){anadirTorsion(NxVec3(-paso,0,0),tipoFuerza);}

	//Modifican la entidad instantaneamente y siendo ABSOLUTO
	void setPlano(float x , float z);
	void setAltura(float y);

	//Modifican la entidad instantaneamente y siendo RELATIVO
	void setAcelerar(float paso);
	void setFrenar(float paso);
	void setSubir(float paso);
	void setBajar(float paso);
	void setEstrafearDerecha(float paso);
	void setEstrafearIzquierda(float paso);

	//Giros instantaneos
	void setGiroYawAbsoluto(float radianes);
	void setGirarDerecha(float paso);
	void setGirarIzquierda(float paso);
	void setMirarArriba(float paso);
	void setMirarAbajo(float paso);
	void setInclinarMiradaDerecha(float paso);
	void setInclinarMiradaIzquierda(float paso);

	void sinFisica();
	void conFisica();
	void noPuedeVolcar();

	NxActor * getActor();
	SceneNode * getRaizSceneNode();
	SceneNode * getHijoSceneNode();
	Entity * getUltimaEntidad();

	float getX();
	float getY();
	float getZ();
	NxVec3 getPos(void);
	string getNombre();

private:

	void postConstruccionComun();
	void postAnadirFormaComun();

	void setX(float x);
	void setY(float y);
	void setZ(float z);

protected:

	SceneNode * raizSceneNode;
	SceneNode * hijoSceneNode;
	NxActor * actorFisica;
	Vector3 posActor;
	Entity * ultimaEntidad;
	NxVec3 tmpTranslacion;

};

#endif